package com.carter.springframework.context.annotation;

import cn.hutool.core.util.StrUtil;
import com.carter.springframework.aop.config.AopBeanRegistryPostProcessor;
import com.carter.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import com.carter.springframework.beans.factory.PropertyPlaceholderConfigurer;
import com.carter.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import com.carter.springframework.beans.factory.config.BeanDefinition;
import com.carter.springframework.beans.factory.config.PropertyValue;
import com.carter.springframework.beans.factory.config.PropertyValues;
import com.carter.springframework.beans.factory.support.BeanDefinitionRegistry;
import com.carter.springframework.stereotype.Component;

import java.util.Set;

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider{
    private BeanDefinitionRegistry registry;

    public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        this.registry = registry;
    }

    public void doScan(String... basePackages){
        for (String basePackage : basePackages) {
            Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
            for (BeanDefinition beanDefinition : candidates) {
                String scope = resolveBeanScope(beanDefinition);
                if (StrUtil.isEmpty(scope)){
                    beanDefinition.setScope(scope);
                }
                registry.registerBeanDefinition(determineBeanName(beanDefinition),beanDefinition);
            }
        }
        registerInnerBean();
    }

    /**
     * 注册spring内部使用的bean
     */
    private void registerInnerBean() {
        //注册处理注解的BeanPostProcessor
        registry.registerBeanDefinition("autowiredAnnotationBeanPostProcessor",new BeanDefinition(AutowiredAnnotationBeanPostProcessor.class));
        //注册处理属性占位符的bean
        BeanDefinition propertyPlaceholder = new BeanDefinition(PropertyPlaceholderConfigurer.class);
        PropertyValues pvs = new PropertyValues();
        pvs.addPropertyValue(new PropertyValue("location", "classpath:application.yml"));
        propertyPlaceholder.setPropertyValues(pvs);
        registry.registerBeanDefinition("propertyPlaceholderConfigurer",propertyPlaceholder);
        //注册AOP相关的bean
        registry.registerBeanDefinition("aopBeanRegistryPostProcessor",new BeanDefinition(AopBeanRegistryPostProcessor.class));
        registry.registerBeanDefinition("defaultAdvisorAutoProxyCreator", new BeanDefinition(DefaultAdvisorAutoProxyCreator.class));
    }

    /**
     * 处理bean的作用域
     * @param beanDefinition
     * @return
     */
    private String resolveBeanScope(BeanDefinition beanDefinition){
        Class<?> beanClass = beanDefinition.getBeanClass();
        Scope scope = beanClass.getAnnotation(Scope.class);
        if (scope!=null){
            return scope.value();
        }
        return StrUtil.EMPTY;
    }

    /**
     * 处理bean名称，以Component配置为准，如果没有配置，则取首字母小写的类名
     * @param beanDefinition
     * @return
     */
    private String determineBeanName(BeanDefinition beanDefinition){
        Class<?> beanClass = beanDefinition.getBeanClass();
        Component component = beanClass.getAnnotation(Component.class);
        String value = component.value();
        if (StrUtil.isEmpty(value)){
            value = StrUtil.lowerFirst(beanClass.getSimpleName());
        }
        return value;
    }
}
